﻿using System;
using NHibernate;
using SellAndBuy.Infrastructure.Core.Logging;

namespace SellAndBuy.Infrastructure.Data.Core
{
    /// <summary>
    /// Logging decorator for Unit of work
    /// </summary>
    public class LoggedUnitOfWork : INhibernateUnitOfWork
    {
        private readonly INhibernateUnitOfWork _factory;
        private readonly ILogger _logger;

        public ISession Session { get { return _factory.Session; } }

        /// <summary>
        /// Constructor
        /// </summary>
        /// <param name="nHibernateFactory">NHibernate factory</param>
        /// <param name="logger">Logger</param>
        /// <exception cref="ArgumentNullException"><paramref name="nHibernateFactory" /> is <c>null</c>.</exception>
        public LoggedUnitOfWork(INhibernateUnitOfWork nHibernateFactory, ILogger logger)
        {
            if (nHibernateFactory == null)
                throw new ArgumentNullException("nHibernateFactory");

            if (logger == null)
                throw new ArgumentNullException("logger");

            _factory = nHibernateFactory;
            _logger = logger;
        }

        /// <summary>
        /// Close session
        /// </summary>
        public void Dispose()
        {
            _factory.Dispose();
        }

        /// <summary>
        /// Commit changes to database
        /// </summary>
        /// <exception cref="InvalidOperationException"><c>InvalidOperationException</c>.</exception>
        public void Commit()
        {
            try
            {
                _logger.Info(this.GetType().ToString(), "Commiting a transaction ...");
                _factory.Commit();
            }
            catch (Exception ex)
            {
                _logger.Error(this.GetType().ToString(), 
                    "Error while commiting transaction, Rolling back", ex);
                throw;
            }
        }

        /// <summary>
        /// Rollback changes to database
        /// </summary>
        /// <returns></returns>
        public void Rollback()
        {
            _logger.Info(this.GetType().ToString(), "Rollback transaction");
            _factory.Rollback();
        }
    }
}